package middleware

import (
	"net/http"
	"strings"
	"time"
	"errors"

	"github.com/gin-gonic/gin"
	"github.com/dgrijalva/jwt-go"
)

var jwtSecret = []byte("airvipisboy")

var (
	tokenExpired     error  = errors.New("Token is expired")
	tokenNotValidYet error  = errors.New("Token not active yet")
	tokenMalformed   error  = errors.New("That's not even a token")
	tokenInvalid     error  = errors.New("Couldn't handle this token:")
	tignKey          string = "newtrekWang"
)

type Claims struct {
	Id string
	jwt.StandardClaims
}

func ReleaseToken(userId, nickName string) (string, error) {
	expirationTime := time.Now().Add(7 * 24 * time.Hour)

	claims := &Claims{
		Id: userId,
		StandardClaims: jwt.StandardClaims{
			Audience:  nickName,              // 受众
			ExpiresAt: expirationTime.Unix(), // 失效时间
			Id:        userId,                //编号
			IssuedAt:  time.Now().Unix(),     // 签发时间
			Issuer:    "airvip",              //签发人
			NotBefore: time.Now().Unix(),     //生效时间
			Subject:   "user token",          //主题
		},
	}
	/* claims := jwt.StandardClaims{
		Audience:  user.Nickname,         // 受众
		ExpiresAt: expirationTime.Unix(), // 失效时间
		Id:        user.Identity,         //编号
		IssuedAt:  time.Now().Unix(),     // 签发时间
		Issuer:    "airvip",              //签发人
		NotBefore: time.Now().Unix(),     //生效时间
		Subject:   "user token",          //主题
	} */

	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := tokenClaims.SignedString(jwtSecret)
	if err != nil {
		return "", err
	}
	return "Bearer " + tokenString, nil

}

// 解析 token
func parseToken(tokenString string) (*Claims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(t *jwt.Token) (interface{}, error) {
		return jwtSecret, nil
	})
	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, tokenMalformed
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				// Token is expired
				return nil, tokenExpired
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, tokenNotValidYet
			} else {
				return nil, tokenInvalid
			}
		}
	}
	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		return claims, nil
	}
	return nil, tokenInvalid
}


func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取 authorization header
		s := c.GetHeader("Authorization")
		if s == "" || !strings.HasPrefix(s, "Bearer ") {

			c.JSON(http.StatusUnauthorized, gin.H{
				"code": 401,
				"msg":  "未携带token, 无权限访问",
			})
			c.Abort()
			return
		}

		token := s[7:]
		// log.Println("get token", token)
		// c2, err := common.ParseToken(token)
		_, err := parseToken(token)
		if err != nil {

			if err == tokenExpired {
				c.JSON(http.StatusOK, gin.H{
					"status": 402,
					"msg":    "授权已过期",
				})
				c.Abort()
				return
			}

			c.JSON(http.StatusUnauthorized, gin.H{
				"code": 403,
				"msg":  err.Error(),
			})
			c.Abort()
			return
		}
		// 验证通过之后获取claim中的数据
		/*uid := c2.Id
		log.Println("user identity is:",c2.StandardClaims.Id)
		user := new(models.UserBasic)
		models.DB.First(&user, uid)
		if user.ID == 0 {
			c.JSON(http.StatusUnauthorized, gin.H{
				"code": 402,
				"msg":  "权限异常",
			})
			c.Abort()
			return
		}
		// 用户存在写入 Context
		// log.Println("user info", *user)
		c.Set("user", user)*/
		c.Next()
	}
}
